package main.gfs;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.TimeZone;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import model.gfs.Ticket;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

/**
 * Отдельный класс для работы с сервером
 * 
 * @author Cobalt
 * 
 */
public class Loader {

	public static String GetHttpsUrl(String url_str)
			throws MalformedURLException, IOException {
		Log.d("loader", url_str);
		HttpURLConnection conn = null;
		// пробуем соединиться.
		URL url = new URL(url_str);
		if (url.getProtocol().toLowerCase().equals("https")) {
			// тут блэк меджик чтоп не ругался на кривые серты и
			// недоверенный домен
			trustAllHosts();
			HttpsURLConnection https = (HttpsURLConnection) url
					.openConnection();
			https.setHostnameVerifier(DO_NOT_VERIFY);
			conn = https;
		} else {
			conn = (HttpURLConnection) url.openConnection();
		}

		String res = "";
		// читаем данные
		BufferedReader rd = new BufferedReader(new InputStreamReader(
				conn.getInputStream()));
		String line = "";
		while ((line = rd.readLine()) != null) {
			res += line;
		}
		conn.disconnect();
		return res;
	}

	public static String PostHttpsUrl(String url_str, String data)
			throws MalformedURLException, IOException {
		// отправим на сервер данные
		HttpURLConnection conn = null;
		String res = ""; // сюда запишем ответ сервера
		URL url = new URL(url_str);
		trustAllHosts();
		HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
		https.setHostnameVerifier(DO_NOT_VERIFY);
		conn = https;
		conn.setDoOutput(true);
		OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
		out.write(data);
		out.close();

		// прочитаем ответ
		BufferedReader in = new BufferedReader(new InputStreamReader(
				conn.getInputStream()));
		String inputLine;
		while ((inputLine = in.readLine()) != null)
			res += inputLine;
		in.close();
		return res;
	}

	public static void ParseTickets(String xml, ArrayList<Ticket> arraytickets)
			throws Exception {
		// теперь надо распарсить полученную XML-ку
		Document doc = null;
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder bulder = factory.newDocumentBuilder();
		doc = bulder.parse(new ByteArrayInputStream(xml.getBytes()));

		Node root = doc.getFirstChild();
		NodeList nodes = root.getChildNodes();
		if (nodes.getLength() > 0) {
			// если в ответ имеет типа ошибки
			if (nodes.item(0).getNodeName().equals("error")) {
				NamedNodeMap attributes = nodes.item(0).getAttributes();
				Node nameAttrib = attributes.getNamedItem("id");
				int id = Integer.parseInt(nameAttrib.getNodeValue());
				switch (id) {
				case 1:
					// ошибка авторизации
					throw (new Exception("Ошибка авторизации"));
				}
			}
			// собсно читаем тикет
			// arraytickets.clear();
			SimpleDateFormat formatter = new SimpleDateFormat(
					"yyyy-MM-dd HH:mm:ss");
			formatter.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
			for (int i = 0; i < nodes.getLength(); i++) {
				Ticket Ticket = new Ticket();
				Ticket.parseXML(nodes.item(i));
				
				if (!arraytickets.contains(Ticket)) { // если такого элемента еще нет
					if (arraytickets.size() > 0) { // если есть хоть один элемент
						if (arraytickets.get(0).getDate().getTime() < Ticket
								.getDate().getTime()) {  // если новый тикет новее первого в списке
							arraytickets.add(0, Ticket); // добавляем его первым
						} else
							arraytickets.add(Ticket); // иначе добавляем старым
					} else
						arraytickets.add(Ticket); // иначе просто добавляем
				}
			}
		}
	}
	
	/**
	 * скачиваем аватарку в кэш
	 * @param id
	 */
	public static boolean downloadImage(Context context,String type,String id){
		File img_file = null;
		if(type.equals("avatars")) img_file = new File(context.getCacheDir(), "/" + id+".gif");
		if(type.equals("ajax")) img_file = new File(context.getCacheDir(), "/img" + id+".jpg");
		
		URL myFileUrl = null;
		try {
			if(type.equals("avatars"))	myFileUrl = new URL("https://www.gfs-team.ru/avatars/" + id+".gif");
			if(type.equals("ajax")) myFileUrl = new URL("https://www.gfs-team.ru/ajax/img.php?id=" + id);
		} catch (Exception e) {
			Log.e("img", "error="+e.getMessage());
			return false;
		}
		
		try {
			HttpsURLConnection https = (HttpsURLConnection) myFileUrl
					.openConnection();
			https.setHostnameVerifier(DO_NOT_VERIFY);
			HttpURLConnection conn = https;
			conn.connect();

			img_file.createNewFile();

			int contentLength = conn.getContentLength();
			InputStream raw = conn.getInputStream();
			InputStream in = new BufferedInputStream(raw);
			byte[] data = new byte[contentLength];
			int bytesRead = 0;
			int offset = 0;
			while (offset < contentLength) {
				bytesRead = in.read(data, offset, data.length - offset);
				if (bytesRead == -1)
					break;
				offset += bytesRead;
			}
			in.close();

			FileOutputStream fw = new FileOutputStream(img_file);
			fw.write(data);
			fw.flush();
			fw.close();
		} catch (Exception e) {
			Log.e("img", "error = "+e.getMessage());
			return false;
		}
		return true;
	}

	/**
	 * берем аватарку из кэша или просим скачать
	 * @param id
	 * @return
	 */
	public static Bitmap getImage(Context context,String type, String id) {
		Bitmap bmImg = null;
		// определимся с путем до аватарки в кэше
		File img_path = new File(context.getCacheDir(), "/");
		if (!img_path.exists())
			img_path.mkdirs();

		File img_file = null;
		if(type.equals("avatars")) img_file = new File(context.getCacheDir(), "/" + id+".gif");
		if(type.equals("ajax")) img_file = new File(context.getCacheDir(), "/img" + id+".jpg");
		
		if (!img_file.exists()) {
			// скачаем аватарку если ее нету в кэше
			if (!downloadImage(context,type, id)) {
				Log.e("img", "файл отсутствует на сервере");
				img_file = new File(context.getCacheDir(), "/no.gif");
			}
		}
		bmImg = BitmapFactory.decodeFile(img_file.getAbsolutePath());
		if(bmImg == null){
			Log.e("img","ошибка кэширования "+img_file.getAbsolutePath());
			img_file = new File(context.getCacheDir(), "/no.gif");
			bmImg = BitmapFactory.decodeFile(img_file.getAbsolutePath());
		}
		return bmImg;
	}

	/**
	 * Тут начинается black-magic весь код, что идет ниже этого коммента,
	 * скопипастен с различных нагугленых ресурсов и его предназначение -
	 * отключить проверку сертификата (доверяем всем сертификатам) и отключить
	 * проверку имени хоста. Нахера это в андройде намучено ваще не знаю, но без
	 * этого валятсо ошибки.
	 * 
	 */
	private static void trustAllHosts() {
		// Create a trust manager that does not validate certificate chains
		TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
				return new java.security.cert.X509Certificate[] {};
			}

			public void checkClientTrusted(X509Certificate[] chain,
					String authType) throws CertificateException {
			}

			public void checkServerTrusted(X509Certificate[] chain,
					String authType) throws CertificateException {
			}
		} };

		// Install the all-trusting trust manager
		try {
			SSLContext sc = SSLContext.getInstance("TLS");
			sc.init(null, trustAllCerts, new java.security.SecureRandom());
			HttpsURLConnection
					.setDefaultSSLSocketFactory(sc.getSocketFactory());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	};
	/* конец блока с black-magic */
}
